from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File as FastAPIFile, Form
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from typing import List, Optional
import os
import shutil
import hashlib
from datetime import datetime

from ..core.database import get_db
from ..models import File, FileType, User, FileVersion
from ..api.auth import get_current_user
from ..schemas.version import FileVersionInfo, FileVersionList, FileVersionCreate, VersionCompare
from ..core.config import settings
from ..core.permissions import check_folder_operation_permission

router = APIRouter(prefix="/files", tags=["versions"])

def calculate_file_checksum(file_path: str) -> str:
    """计算文件的MD5校验和"""
    hash_md5 = hashlib.md5()
    with open(file_path, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()

@router.get("/{file_id}/versions", response_model=FileVersionList)
async def get_file_versions(
    file_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取文件的所有版本"""
    # 检查文件是否存在
    file = db.query(File).filter(File.id == file_id, File.is_deleted == False).first()
    if not file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    # 检查权限
    if file.file_type == FileType.FOLDER:
        raise HTTPException(status_code=400, detail="文件夹不支持版本管理")
    
    if file.parent_id and not check_folder_operation_permission(file.parent_id, current_user, "read", db):
        raise HTTPException(status_code=403, detail="没有权限访问此文件")
    
    # 获取版本列表
    versions = db.query(FileVersion).filter(
        FileVersion.file_id == file_id,
        FileVersion.is_deleted == False
    ).order_by(FileVersion.version_number.desc()).all()
    
    # 构建版本信息
    version_list = []
    current_version = None
    
    for version in versions:
        creator = db.query(User).filter(User.id == version.created_by).first()
        version_info = FileVersionInfo(
            id=version.id,
            file_id=version.file_id,
            version_number=version.version_number,
            size=version.size,
            mime_type=version.mime_type,
            checksum=version.checksum,
            comment=version.comment,
            created_by=version.created_by,
            creator_name=creator.full_name if creator else "未知用户",
            is_current=version.is_current,
            created_at=version.created_at
        )
        version_list.append(version_info)
        
        if version.is_current:
            current_version = version.version_number
    
    return FileVersionList(
        versions=version_list,
        total=len(version_list),
        current_version=current_version
    )

@router.post("/{file_id}/versions", response_model=FileVersionInfo)
async def create_file_version(
    file_id: int,
    file: UploadFile = FastAPIFile(...),
    comment: str = Form(""),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """创建文件的新版本"""
    # 检查文件是否存在
    original_file = db.query(File).filter(File.id == file_id, File.is_deleted == False).first()
    if not original_file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    if original_file.file_type == FileType.FOLDER:
        raise HTTPException(status_code=400, detail="文件夹不支持版本管理")
    
    # 检查权限
    if original_file.parent_id and not check_folder_operation_permission(original_file.parent_id, current_user, "write", db):
        raise HTTPException(status_code=403, detail="没有权限修改此文件")
    
    # 获取当前最大版本号
    max_version = db.query(FileVersion.version_number).filter(
        FileVersion.file_id == file_id,
        FileVersion.is_deleted == False
    ).order_by(FileVersion.version_number.desc()).first()
    
    new_version_number = (max_version[0] if max_version else 0) + 1
    
    # 创建版本目录
    version_dir = os.path.join(settings.UPLOAD_DIR, "versions", str(file_id))
    os.makedirs(version_dir, exist_ok=True)
    
    # 保存新版本文件
    version_filename = f"v{new_version_number}_{file.filename}"
    version_path = os.path.join(version_dir, version_filename)
    
    with open(version_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    
    # 计算校验和
    checksum = calculate_file_checksum(version_path)
    
    # 将之前的当前版本标记为非当前
    db.query(FileVersion).filter(
        FileVersion.file_id == file_id,
        FileVersion.is_current == True
    ).update({"is_current": False})
    
    # 创建新版本记录
    new_version = FileVersion(
        file_id=file_id,
        version_number=new_version_number,
        path=version_path,
        size=file.size,
        mime_type=file.content_type,
        checksum=checksum,
        comment=comment,
        created_by=current_user.id,
        is_current=True
    )
    
    db.add(new_version)
    
    # 更新原文件信息
    original_file.size = file.size
    original_file.mime_type = file.content_type
    original_file.updated_at = datetime.utcnow()
    
    db.commit()
    db.refresh(new_version)
    
    return FileVersionInfo(
        id=new_version.id,
        file_id=new_version.file_id,
        version_number=new_version.version_number,
        size=new_version.size,
        mime_type=new_version.mime_type,
        checksum=new_version.checksum,
        comment=new_version.comment,
        created_by=new_version.created_by,
        creator_name=current_user.full_name,
        is_current=new_version.is_current,
        created_at=new_version.created_at
    )

@router.get("/{file_id}/versions/{version_number}/download")
async def download_file_version(
    file_id: int,
    version_number: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """下载指定版本的文件"""
    # 检查文件是否存在
    file = db.query(File).filter(File.id == file_id, File.is_deleted == False).first()
    if not file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    # 检查权限
    if file.parent_id and not check_folder_operation_permission(file.parent_id, current_user, "read", db):
        raise HTTPException(status_code=403, detail="没有权限访问此文件")
    
    # 获取指定版本
    version = db.query(FileVersion).filter(
        FileVersion.file_id == file_id,
        FileVersion.version_number == version_number,
        FileVersion.is_deleted == False
    ).first()
    
    if not version:
        raise HTTPException(status_code=404, detail="版本不存在")
    
    if not os.path.exists(version.path):
        raise HTTPException(status_code=404, detail="版本文件不存在")
    
    return FileResponse(
        version.path,
        filename=f"{file.name}_v{version_number}",
        media_type=version.mime_type
    )

@router.post("/{file_id}/versions/{version_number}/restore")
async def restore_file_version(
    file_id: int,
    version_number: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """恢复到指定版本"""
    # 检查文件是否存在
    file = db.query(File).filter(File.id == file_id, File.is_deleted == False).first()
    if not file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    # 检查权限
    if file.parent_id and not check_folder_operation_permission(file.parent_id, current_user, "write", db):
        raise HTTPException(status_code=403, detail="没有权限修改此文件")
    
    # 获取指定版本
    target_version = db.query(FileVersion).filter(
        FileVersion.file_id == file_id,
        FileVersion.version_number == version_number,
        FileVersion.is_deleted == False
    ).first()
    
    if not target_version:
        raise HTTPException(status_code=404, detail="版本不存在")
    
    if not os.path.exists(target_version.path):
        raise HTTPException(status_code=404, detail="版本文件不存在")
    
    # 将当前版本标记为非当前
    db.query(FileVersion).filter(
        FileVersion.file_id == file_id,
        FileVersion.is_current == True
    ).update({"is_current": False})
    
    # 标记目标版本为当前版本
    target_version.is_current = True
    
    # 更新原文件信息
    file.size = target_version.size
    file.mime_type = target_version.mime_type
    file.updated_at = datetime.utcnow()
    
    # 复制版本文件到原文件位置
    shutil.copy2(target_version.path, file.path)
    
    db.commit()
    
    return {"message": f"已恢复到版本 {version_number}"}

@router.delete("/{file_id}/versions/{version_number}")
async def delete_file_version(
    file_id: int,
    version_number: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """删除指定版本"""
    # 检查文件是否存在
    file = db.query(File).filter(File.id == file_id, File.is_deleted == False).first()
    if not file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    # 检查权限
    if file.parent_id and not check_folder_operation_permission(file.parent_id, current_user, "delete", db):
        raise HTTPException(status_code=403, detail="没有权限删除此文件版本")
    
    # 获取指定版本
    version = db.query(FileVersion).filter(
        FileVersion.file_id == file_id,
        FileVersion.version_number == version_number,
        FileVersion.is_deleted == False
    ).first()
    
    if not version:
        raise HTTPException(status_code=404, detail="版本不存在")
    
    # 不能删除当前版本
    if version.is_current:
        raise HTTPException(status_code=400, detail="不能删除当前版本")
    
    # 标记版本为已删除
    version.is_deleted = True
    
    # 删除物理文件
    if os.path.exists(version.path):
        os.remove(version.path)
    
    db.commit()
    
    return {"message": f"版本 {version_number} 已删除"}

@router.get("/{file_id}/versions/compare/{version1}/{version2}", response_model=VersionCompare)
async def compare_file_versions(
    file_id: int,
    version1: int,
    version2: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """比较两个版本"""
    # 检查文件是否存在
    file = db.query(File).filter(File.id == file_id, File.is_deleted == False).first()
    if not file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    # 检查权限
    if file.parent_id and not check_folder_operation_permission(file.parent_id, current_user, "read", db):
        raise HTTPException(status_code=403, detail="没有权限访问此文件")
    
    # 获取两个版本
    v1 = db.query(FileVersion).filter(
        FileVersion.file_id == file_id,
        FileVersion.version_number == version1,
        FileVersion.is_deleted == False
    ).first()
    
    v2 = db.query(FileVersion).filter(
        FileVersion.file_id == file_id,
        FileVersion.version_number == version2,
        FileVersion.is_deleted == False
    ).first()
    
    if not v1 or not v2:
        raise HTTPException(status_code=404, detail="版本不存在")
    
    # 获取创建者信息
    creator1 = db.query(User).filter(User.id == v1.created_by).first()
    creator2 = db.query(User).filter(User.id == v2.created_by).first()
    
    # 计算差异
    size_diff = v2.size - v1.size
    time_diff = str(v2.created_at - v1.created_at)
    
    return VersionCompare(
        version1=FileVersionInfo(
            id=v1.id,
            file_id=v1.file_id,
            version_number=v1.version_number,
            size=v1.size,
            mime_type=v1.mime_type,
            checksum=v1.checksum,
            comment=v1.comment,
            created_by=v1.created_by,
            creator_name=creator1.full_name if creator1 else "未知用户",
            is_current=v1.is_current,
            created_at=v1.created_at
        ),
        version2=FileVersionInfo(
            id=v2.id,
            file_id=v2.file_id,
            version_number=v2.version_number,
            size=v2.size,
            mime_type=v2.mime_type,
            checksum=v2.checksum,
            comment=v2.comment,
            created_by=v2.created_by,
            creator_name=creator2.full_name if creator2 else "未知用户",
            is_current=v2.is_current,
            created_at=v2.created_at
        ),
        size_diff=size_diff,
        time_diff=time_diff
    )